#!/bin/bash
#
# Copyright(c) 2012-2021 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause
#

############################################################
#                         GLOBALS                          #
############################################################

export LOG_FILE=""
export LOG_NAME="out"
export RESULT_FILE="result"
export CUMULATIVE_LOG="cumulative_log"
export EXEC_LOG="exec_log"
export TESTS=0
export PASSED=0
export FAILED=0
export NOT_RUN=0

# Some tests might use additional logging mechanism - disable them in case we run the tests via this script.
export DISABLE_EXTERNAL_LOGGING=1

############################################################
#                        FUNCTIONS                         #
############################################################

check_result() {
    if [ $1 == 0 ]; then
        echo -n "     "
        echo_green_n "[OK]"
        PASSED=$(($PASSED + 1))
        TEST_RESULTS[$TESTS]="Passed"
    elif [ "$1" -eq "$CAS_TEST_NOT_RUN" ]; then
        echo_yellow_n "[NOT RUN]"
        NOT_RUN=$(($NOT_RUN + 1))
        TEST_RESULTS[$TESTS]="Not_run"
    else
        echo -n "  "
        echo_red_n "[ERROR]"
        FAILED=$(($FAILED+ 1))
        TEST_RESULTS[$TESTS]="Failed"
    fi
}

print_time() {
    time=$1
    hours=`expr $time / 3600`
    mins=`expr \( $time - $hours \* 3600 \) / 60`
    secs=`expr $time - $hours \* 3600 - $mins \* 60`
    printf "%5d[s] (%02d:%02d:%02d)" ${time} ${hours} ${mins} ${secs}
}

run_test() {
    TEST_FILE=$1
    TEST_FILE_NAMES[$TESTS]=${TEST_FILE}
    TEST_NAMES[$TESTS]="$(basename $TEST_FILE)"
    # Ignore tests marked as not-working
    if [[ ${TEST_NAMES[$TESTS]} == _* ]] ; then
        return
    fi
    TEST_CATEGORIES[$TESTS]="$(dirname $TEST_FILE | sed 's/.*\///g')"
    DESCRIPTION=$(cat $TEST_FILE | grep "# DESCRIPTION" | sed 's/# DESCRIPTION //g')
    DESCRIPTION=${DESCRIPTION:0:80}
    if [ -z "$DESCRIPTION" ] ; then
        DESCRIPTION="${TEST_NAMES[$TESTS]} [NO DESCRIPTION]"
    fi
    TEST_DESCRIPTIONS[$TESTS]="$DESCRIPTION"
    printf "%3d. %-30s% -80s" $((TESTS+1)) "${TEST_FILE}" "$DESCRIPTION" | tee -a ${EXEC_LOG}
    # Clear system log
    dmesg -c &> /dev/null

    export TEST_LOG_DIR="${LOGS_FOLDER}/$TEST_FILE"
    if [ ! -d $TEST_LOG_DIR ] ; then
        mkdir -p $TEST_LOG_DIR
    fi
    export LOG_FILE=$TEST_LOG_DIR/$LOG_NAME
    # Execute test and save output to the log file

    TEST_TIME="$(date +%s)"
    # Check result and print to stdout
    bash $TEST_FILE >> $LOG_FILE
    status=$?
    check_result $status

    if [ $status == 0 ]; then
        echo -n "     [OK]" >> ${EXEC_LOG}
    elif [ "$status" == "$CAS_TEST_NOT_RUN" ]; then
        echo -n "[NOT RUN]" >> ${EXEC_LOG}
    else
        echo -n "  [ERROR]" >> ${EXEC_LOG}
    fi

    delta=$(($(date +%s) - TEST_TIME))
    print_time ${delta} | tee -a ${EXEC_LOG}
    echo "" | tee -a ${EXEC_LOG}
    cat $LOG_FILE >> $LOGS_FOLDER/$CUMULATIVE_LOG

    # Store test time
    TEST_TIMES[$TESTS]="${delta}"
    # Print the kernel log
    echo "--- kernel log ---" | tee -a $LOGS_FOLDER/$CUMULATIVE_LOG >> $LOG_FILE
    dmesg | tee -a $LOGS_FOLDER/$CUMULATIVE_LOG >> $LOG_FILE
    echo "" | tee -a $LOGS_FOLDER/$CUMULATIVE_LOG >> $LOG_FILE
    # Increment the tests counter
    TESTS=$(($TESTS + 1))
}

start_table() {
    printf "<h3>%s tests</h3>\n" ${2} >> ${1}
    printf "<table style=\"width:100%%\">\n" >> ${1}
    printf "\t<tr bgcolor=\"pink\" style=\"font-weight: bold\">\n" >> ${1}
    printf "\t\t<td style=\"width: 20%%\">%s</td>\n" "Test file name" >> ${1}
    printf "\t\t<td style=\"width: 60%%\">%s</td>\n" "Test description" >> ${1}
    printf "\t\t<td style=\"width: 15%%\">%s</td>\n" "Exec time" >> ${1}
    printf "\t\t<td>%s</td>\n" "Result" >> ${1}
    printf "\t</tr>\n" >> ${1}
}

stop_table() {
    printf "</table><br />\n" >> ${1}
}

export_results_to_html() {
    HTML_PASSED_LOG="${LOG_FILE}-passed.html"
    HTML_FAILED_LOG="${LOG_FILE}-failed.html"
    HTML_NOT_RUN_LOG="${LOG_FILE}-not-run.html"
    HTML_LOG="${LOG_FILE}.html"
    BUILD=$(cas_version)
    IF=`route | grep default | tr -s ' ' | cut -d' ' -f8`
    IP=`ifconfig ${IF} | grep "inet " | tr -s ' ' | cut -d' ' -f3`
    HOSTNAME=`hostname`

    rm -f ${HTML_LOG} ${HTML_PASSED_LOG} ${HTML_FAILED_LOG} ${HTML_NOT_RUN_LOG}
    touch ${HTML_LOG} ${HTML_PASSED_LOG} ${HTML_FAILED_LOG} ${HTML_NOT_RUN_LOG}

    printf "<h2>Summary for <u>Open-CAS-%s</u></h2>\n" "${BUILD}" >> ${HTML_LOG}
    printf "<h2>Test mode: %s</h2>\n" "${TEST_MODE}" >> ${HTML_LOG}
    printf "<h2>HOST: %s (%s)</h2>\n" "${IP}" "${HOSTNAME}" >> ${HTML_LOG}

    start_table ${HTML_PASSED_LOG} "PASSED"
    start_table ${HTML_FAILED_LOG} "FAILED"
    start_table ${HTML_NOT_RUN_LOG} "NOT_RUN"

    total_passed=0
    total_failed=0
	total_not_run=0

    for ((I = 0; I < $TESTS; I++)) ; do
        if [ "${TEST_RESULTS[$I]}" == "Passed" ]; then
            COLOR="green"
            file=${HTML_PASSED_LOG}
            total_passed=$((${total_passed}+${TEST_TIMES[I]}))
        elif [ "${TEST_RESULTS[$I]}" == "Failed" ]; then
            COLOR="red"
            file=${HTML_FAILED_LOG}
            total_failed=$((${total_failed}+${TEST_TIMES[$I]}))
        else
            COLOR="yellow"
            file=${HTML_NOT_RUN_LOG}
            total_not_run=$((${total_not_run}+${TEST_TIMES[I]}))
        fi

        printf "\t<tr>\n" >> ${file}
        printf "\t\t<td>%s</td>\n" "${TEST_FILE_NAMES[$I]}" >> ${file}
        printf "\t\t<td>%s</td>\n" "${TEST_DESCRIPTIONS[$I]}" >> ${file}
        printf "\t\t<td>%s</td>\n" "`print_time ${TEST_TIMES[$I]}`" >> ${file}
        printf "\t\t<td><font color=\"$COLOR\">%s</font></td>\n" "${TEST_RESULTS[$I]}" >> ${file}
        printf "\t</tr>\n" >> ${file}
    done

    stop_table ${HTML_PASSED_LOG}
    stop_table ${HTML_FAILED_LOG}
    stop_table ${HTML_NOT_RUN_LOG}

    if [ ${PASSED} -gt 0 ]; then
        cat ${HTML_PASSED_LOG} >> ${HTML_LOG}
    fi

    if [ ${FAILED} -gt 0 ]; then
        cat ${HTML_FAILED_LOG} >> ${HTML_LOG}
    fi

    if [ ${NOT_RUN} -gt 0 ]; then
        cat ${HTML_NOT_RUN_LOG} >> ${HTML_LOG}
    fi

    printf "<br />\n" >> ${HTML_LOG}

    printf "<h3>Time stats</h3>\n" >> ${HTML_LOG}
    printf "<table style=\"width: 500px\">\n" >> ${HTML_LOG}

    printf "\t<tr bgcolor=\"pink\" style=\"font-weight: bold\">\n" >> ${HTML_LOG}
    printf "\t\t<td style=\"width: 40%%\">Name</td>\n" >> ${HTML_LOG}
    printf "\t\t<td style=\"width: 40%%\">Time</td>\n" >> ${HTML_LOG}
    printf "\t<td style=\"width: 20%%\">Number</td>\n" >> ${HTML_LOG}
    printf "\t</tr>\n" >> ${HTML_LOG}

    printf "\t<tr>\n" >> ${HTML_LOG}
    time=`print_time ${total_passed}`
    printf "\t\t<td>Passed</td>\n" >> ${HTML_LOG}
    printf "\t\t<td>%s</td>\n" "${time}" >> ${HTML_LOG}
    printf "\t\t<td>%d</td>\n" ${PASSED} >> ${HTML_LOG}
    printf "\t</tr>\n" >> ${HTML_LOG}

    printf "\t<tr>\n" >> ${HTML_LOG}
    time=`print_time ${total_failed}`
    printf "\t\t<td>Failed</td>\n" >> ${HTML_LOG}
    printf "\t\t<td>%s</td>\n" "${time}" >> ${HTML_LOG}
    printf "\t\t<td>%d</td>\n" ${FAILED} >> ${HTML_LOG}
    printf "\t</tr>\n" >> ${HTML_LOG}

    printf "\t<tr>\n" >> ${HTML_LOG}
    time=`print_time ${total_not_run}`
    printf "\t\t<td>Not run</td>\n" >> ${HTML_LOG}
    printf "\t\t<td>%s</td>\n" "${time}" >> ${HTML_LOG}
    printf "\t\t<td>%d</td>\n" ${NOT_RUN} >> ${HTML_LOG}
    printf "\t</tr>\n" >> ${HTML_LOG}

    printf "\t<tr style=\"font-weight: bold\">\n" >> ${HTML_LOG}
    time=`print_time $((total_passed+total_failed+total_not_run))`
    printf "\t\t<td>Total</td>\n" >> ${HTML_LOG}
    printf "\t\t<td>%s</td>\n" "${time}" >> ${HTML_LOG}
    printf "\t\t<td>%d</td>\n" ${TESTS} >> ${HTML_LOG}
    printf "\t</tr>\n" >> ${HTML_LOG}

    printf "</table>\n" >> ${HTML_LOG}

    printf "<h3>Detailed execution with order</h3>\n" >> ${HTML_LOG}

    printf "<pre>\n" >> ${HTML_LOG}
    cat ${EXEC_LOG} >> ${HTML_LOG}
    rm -f ${EXEC_LOG}
    printf "</pre>\n" >> ${HTML_LOG}

    printf "<br />\n" >> ${HTML_LOG}

    printf "<i>More details in %s</i>\n" ${LOGS_FOLDER} >> ${HTML_LOG}

    cp ${HTML_LOG} ${LOGS_FOLDER}/results.html
    rm -f ${HTML_LOG} ${HTML_PASSED_LOG} ${HTML_FAILED_LOG} ${HTML_NOT_RUN_LOG}
}

add_header() {
    echo "" >> $1
    echo "--- ${2} tests ---" >> $1
    printf "%-16s %-10s %-80s %20s %10s\n" "Test group" "Name" "Test description" "Exec time" "Result" >> $1
    for I in {0..139}; do
            echo -n '-' >> $1
    done
    echo "" >> $1
}

sum_up_and_exit() {
    TMP_PASSED="/tmp/cas_passed.txt"
    TMP_FAILED="/tmp/cas_failed.txt"
    TMP_NOT_RUN="/tmp/cas_not_run.txt"

    rm -f ${TMP_PASSED} ${TMP_FAILED} ${TMP_NOT_RUN}
    touch ${TMP_PASSED} ${TMP_FAILED} ${TMP_NOT_RUN}

    add_header ${TMP_PASSED} "PASSED"
    add_header ${TMP_FAILED} "FAILED"
    add_header ${TMP_NOT_RUN} "NOT_RUN"

    total_passed=0
    total_failed=0
	total_not_run=0

    for ((I = 0; I < $TESTS; I++)) ; do
        if [ "${TEST_RESULTS[$I]}" == "Passed" ]; then
            file=${TMP_PASSED}
            total_passed=$((${total_passed}+${TEST_TIMES[I]}))
        elif [ "${TEST_RESULTS[$I]}" == "Failed" ]; then
            file=${TMP_FAILED}
            total_failed=$((${total_failed}+${TEST_TIMES[$I]}))
        else
            file=${TMP_NOT_RUN}
            total_not_run=$((${total_not_run}+${TEST_TIMES[$I]}))
		fi
        printf "%-16s %-10s %-80s %20s %10s\n" "${TEST_CATEGORIES[$I]}" "${TEST_NAMES[$I]}" "${TEST_DESCRIPTIONS[$I]}" "`print_time ${TEST_TIMES[$I]}`" "${TEST_RESULTS[$I]}" >> ${file}
    done

    if [ ${PASSED} -gt 0 ]; then
        cat ${TMP_PASSED}
    fi

    if [ ${FAILED} -gt 0 ]; then
        cat ${TMP_FAILED}
    fi

	if [ ${NOT_RUN} -gt 0 ]; then
		cat ${TMP_NOT_RUN}
	fi

    rm -f ${TMP_PASSED} ${TMP_FAILED} ${TMP_NOT_RUN}

    echo ""
    time=`print_time $((total_passed+total_failed))`
    tests_no=`printf "%3d" $TESTS`
    echo "Tests number: ${tests_no} ${time}"

    tests_no=`printf "%3d" $PASSED`
    echo_green_n "Passed:       ${tests_no} "
    print_time ${total_passed}
    echo ""

    tests_no=`printf "%3d" $FAILED`
    echo_red_n "Failed:       ${tests_no} "
    print_time ${total_failed}
    echo ""

    tests_no=`printf "%3d" $NOT_RUN`
    echo_yellow_n "Not run:      ${tests_no} "
    print_time ${total_not_run}
    echo ""
    echo ""

    echo "More details in $LOGS_FOLDER"
    export_results_to_html
    if [ $(($PASSED + $NOT_RUN)) == $TESTS ] ; then
        exit 0
    else
        exit 1
    fi
}

############################################################
#                          MAIN                            #
############################################################

BVT_TEST_HEADER="# USE_IN_BVT"
NIGHTLY_TEST_HEADER="# USE_IN_NIGHTLY"
ATOMIC_TEST_HEADER="# USE_IN_ATOMIC"
TEST_FILE_PATTERN="[0-9*]*"
TEST_MODE=""
TEST_FILES=""
TEST_NAMES=""
TEST_DESCRIPTIONS=""
TEST_RESULTS=""

TESTS_DIR="$(dirname $0)"
. $TESTS_DIR/cas_lib

if [ $# -eq 0 ] ; then
    usage
    exit 1
fi

load_cas_lib
parse_args $*
check_config
set_categories

case $TEST_MODE in
    "all" | "dir" )
        for CATEGORY in $CATEGORIES ; do
            TEST_FILES="$(find $CATEGORY -type f -name "$TEST_FILE_PATTERN" | sort) $TEST_FILES"
        done
        ;;
    "sanity" )
        TEST_FILES=$(find $TESTS_DIR/sandbox -type f -name "$TEST_FILE_PATTERN" | sort)
        ;;
    "bvt" )
        for CATEGORY in $CATEGORIES ; do
            TEST_FILES="$TEST_FILES $(find $CATEGORY -type f -name "$TEST_FILE_PATTERN" | xargs grep -l "$BVT_TEST_HEADER" | sort)"
        done
        ;;
    "nightly" )
        for CATEGORY in $CATEGORIES ; do
            TEST_FILES="$TEST_FILES $(find $CATEGORY -type f -name "$TEST_FILE_PATTERN" | xargs grep -l "$NIGHTLY_TEST_HEADER" | sort)"
        done
        ;;
    * )
        echo "Unsupported test mode $TEST_MODE"
        exit 1
esac

echo "--- Starting test mode $TEST_MODE ---"
echo ""

rm -f ${EXEC_LOG}
touch ${EXEC_LOG}
for TEST in $TEST_FILES ; do
    logger "[CAS][DVT] ~~~ $TEST ~~~ [START]" &>/dev/null
    run_test $TEST
    logger "[CAS][DVT] ~~~ $TEST ~~~ [END]" &>/dev/null
done

sum_up_and_exit | tee -a $LOGS_FOLDER/$RESULT_FILE
exec_result=${PIPESTATUS[0]}

rm -f ${EXEC_LOG}

exit ${exec_result}
